metadata: change resolve serialization
authorAleksey Kladov <aleksey.kladov@gmail.com>
Fri, 29 Jan 2016 20:47:16 +0000 (23:47 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Fri, 29 Jan 2016 22:34:44 +0000 (01:34 +0300)
src/cargo/ops/cargo_output_metadata.rs
tests/test_cargo_metadata.rs

index 33be1857f6f7b70e922f37cd5f2c6cc67fff7c1e..a5ebdc10094371e3e35561c8b7ab2909d5f59de3 100644 (file)
@@ -1,7 +1,9 @@
 use std::path::Path;
 
+use rustc_serialize::{Encodable, Encoder};
+
 use core::resolver::Resolve;
-use core::{Source, Package};
+use core::{Source, Package, PackageId};
 use ops;
 use sources::PathSource;
 use util::config::Config;
@@ -19,9 +21,7 @@ pub struct OutputMetadataOptions<'a> {
 /// Loads the manifest, resolves the dependencies of the project to the concrete
 /// used versions - considering overrides - and writes all dependencies in a JSON
 /// format to stdout.
-pub fn output_metadata<'a>(opt: OutputMetadataOptions,
-                           config: &'a Config)
-                           -> CargoResult<ExportInfo> {
+pub fn output_metadata(opt: OutputMetadataOptions, config: &Config) -> CargoResult<ExportInfo> {
     let deps = try!(resolve_dependencies(opt.manifest_path,
                                          config,
                                          opt.features,
@@ -31,7 +31,7 @@ pub fn output_metadata<'a>(opt: OutputMetadataOptions,
     assert_eq!(opt.version, VERSION);
     Ok(ExportInfo {
         packages: packages,
-        resolve: resolve,
+        resolve: MetadataResolve(resolve),
         version: VERSION,
     })
 }
@@ -39,10 +39,45 @@ pub fn output_metadata<'a>(opt: OutputMetadataOptions,
 #[derive(RustcEncodable)]
 pub struct ExportInfo {
     packages: Vec<Package>,
-    resolve: Resolve,
+    resolve: MetadataResolve,
     version: u32,
 }
 
+/// Newtype wrapper to provide a custom `Encodable` implementation.
+/// The one from lockfile does not fit because it uses a non-standard
+/// format for `PackageId`s
+struct MetadataResolve(Resolve);
+
+impl Encodable for MetadataResolve {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        #[derive(RustcEncodable)]
+        struct EncodableResolve<'a> {
+            root: &'a PackageId,
+            nodes: Vec<Node<'a>>,
+        }
+
+        #[derive(RustcEncodable)]
+        struct Node<'a> {
+            id: &'a PackageId,
+            dependencies: Vec<&'a PackageId>,
+        }
+
+        let resolve = &self.0;
+        let encodable = EncodableResolve {
+            root: resolve.root(),
+            nodes: resolve.iter().map(|id| {
+                Node {
+                    id: id,
+                    dependencies: resolve.deps(id)
+                        .map(|it| it.collect())
+                        .unwrap_or(Vec::new()),
+                }
+            }).collect(),
+        };
+
+        encodable.encode(s)
+    }
+}
 
 /// Loads the manifest and resolves the dependencies of the project to the
 /// concrete used versions. Afterwards available overrides of dependencies are applied.
index 09afbb2fc1d74ba4c3a6d9a6b23cd2287927ef5f..e62cb186ff0bd58e425f45506bb3dffa20a4b696 100644 (file)
@@ -1,4 +1,4 @@
-use hamcrest::{assert_that, existing_file};
+use hamcrest::assert_that;
 use support::registry::Package;
 use support::{project, execs, basic_bin_manifest};
 
@@ -32,14 +32,13 @@ test!(cargo_metadata_simple {
             }
         ],
         "resolve": {
-            "package": [],
-            "root": {
-                "name": "foo",
-                "version": "0.5.0",
-                "source": null,
-                "dependencies" : []
-            },
-            "metadata": null
+            "nodes": [
+                {
+                    "dependencies": [],
+                    "id": "foo 0.5.0 (path+file:[..]foo)"
+                }
+            ],
+            "root": "foo 0.5.0 (path+file:[..]foo)"
         },
         "version": 1
     }"#));
@@ -146,31 +145,25 @@ test!(cargo_metadata_with_deps {
             }
         ],
         "resolve": {
-            "metadata": null,
-            "package": [
+            "nodes": [
+                {
+                    "dependencies": [
+                        "bar 0.0.1 (registry+file:[..])"
+                    ],
+                    "id": "foo 0.5.0 (path+file:[..]foo)"
+                },
                 {
                     "dependencies": [
                         "baz 0.0.1 (registry+file:[..])"
                     ],
-                    "name": "bar",
-                    "source": "registry+file:[..]",
-                    "version": "0.0.1"
+                    "id": "bar 0.0.1 (registry+file:[..])"
                 },
                 {
                     "dependencies": [],
-                    "name": "baz",
-                    "source": "registry+file:[..]",
-                    "version": "0.0.1"
+                    "id": "baz 0.0.1 (registry+file:[..])"
                 }
             ],
-            "root": {
-                "dependencies": [
-                    "bar 0.0.1 (registry+file:[..])"
-                ],
-                "name": "foo",
-                "source": null,
-                "version": "0.5.0"
-            }
+            "root": "foo 0.5.0 (path+file:[..]foo)"
         },
         "version": 1
     }"#));